package com.googlecode.gwt.commons.logging.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.MissingResourceException;


import org.apache.commons.logging.ILogLevel;
import org.apache.commons.logging.LogService;
import org.apache.commons.logging.LogServiceAsync;
import org.apache.commons.logging.impl.LogMessage;

import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.Dictionary;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;

public abstract class LogTimer extends Timer implements ILogLevel {

	/**
	 * @gwt.typeArgs<org.apache.commons.logging.impl.LogMessage>
	 */
	private static List fifoLogForServer = new ArrayList();

	private static LogServiceAsync proxy;

	private static int periodo = 10000;
	
	/**
	 * Get the level log of client 
	 * @param level
	 * @return LevelConstant - a specific level
	 */
	public abstract LevelConstant getLevelConstant(int level);
	
	// Get property timer and log_server path
	public LogTimer() {
		if (proxy == null) {
			proxy = (LogServiceAsync) GWT.create(LogService.class);
			String serviceURL;
			try {
				Dictionary applicationDictionary = Dictionary.getDictionary("Application");
				serviceURL = applicationDictionary.get("log_servlet_url");
				String cvalue = applicationDictionary.get("timer");
				try {
					periodo = Integer.parseInt(cvalue);
				} 
				catch (NumberFormatException e) {
				}
			} catch (MissingResourceException e) {
				serviceURL = "/logger";
			}
			ServiceDefTarget target = (ServiceDefTarget) proxy;
			target.setServiceEntryPoint(GWT.getModuleBaseURL() + serviceURL);
		}
	}

	public void addLog(LevelConstant level, String cname, String method, String msg, Throwable ex) {
		fifoLogForServer.add(new LogMessage(level, cname, method, msg, ex));
	}

	
	/**
	 * Start to send a list of client log
	 *
	 */
	public void start() {
		fifoLogForServer = new ArrayList();
		scheduleRepeating(periodo);
	}
	
	/**
	 * Stop to send a list of client log
	 *
	 */
	public void stop() {
		cancel();
		
		//invio gli ultimi
		run();
		fifoLogForServer = new ArrayList();
	}
	
	/**
	 * send a list of client log 
	 *
	 */
	public void run() {
		if (fifoLogForServer.size() > 0) {
			// Blocco momentaneamente il timer fino a che non ha risposto la
			// callback
			cancel();

			/**
			 * @gwt.typeArgs<org.apache.commons.logging.impl.LogMessage>
			 */			
			final List temp = new ArrayList();
			temp.addAll(fifoLogForServer);
			fifoLogForServer = new ArrayList();
			
			proxy.sendLog(temp, new AsyncCallback() {
				public void onFailure(Throwable caught) {
					//Se il servizio è andato male riprovo a rinviare i log al prossimo tick
					fifoLogForServer.addAll(0, temp);
					
					// faccio ripartire il timer
					scheduleRepeating(periodo);
				}

				public void onSuccess(Object result) {
					// faccio ripartire il timer
					scheduleRepeating(periodo);
				}
			});
		}
	}
	
	
	
}
